package com.skyd.core.android.game;

import java.util.Date;

import com.skyd.core.vector.Vector2DF;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

/**
 * 动态壁纸类，继承自WallpaperService
 * 
 * @author SkyD
 * 
 */
public abstract class GameWallpaperService extends WallpaperService implements
		IGameDisplayBase {

	private final Handler handler = new Handler();

	@Override
	public Engine onCreateEngine() {
		return new GameEngine();
	}

	/**
	 * 初始值为true。 功能注释：指示是否为首次显示，在第一次surfaceCreated事件之后变为false
	 */
	private Boolean _IsFirstShow = true;

	/**
	 * 获取IsFirstShow。 功能注释：指示是否为首次显示，在第一次surfaceCreated事件之后变为false
	 * 
	 * @return 当前的Boolean类型的值
	 */
	public Boolean getIsFirstShow() {
		return _IsFirstShow;
	}

	/**
	 * 初始值为false。 功能注释：指示当前是否执行线程刷新操作
	 */
	private boolean _Runnable = false;

	/**
	 * 获取Runnable。 功能注释：指示当前是否执行线程刷新操作
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getRunnable() {
		return _Runnable;
	}

	/**
	 * 设置Runnable。 功能注释：指示当前是否执行线程刷新操作
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	public void setRunnable(boolean value) {
		_Runnable = value;
	}

	/**
	 * 设置Runnable为其默认值(false)。 功能注释：指示当前是否执行线程刷新操作
	 */
	public void setRunnableToDefault() {
		setRunnable(false);
	}

	/**
	 * 初始值为60。 功能注释：每秒显示帧数
	 */
	private int _FPS = 60;

	/**
	 * 获取FPS。 功能注释：每秒显示帧数
	 * 
	 * @return 当前的int类型的值
	 */
	public int getFPS() {
		return _FPS;
	}

	/**
	 * 设置FPS。(应当在复写surfaceCreated方法中执行此操作，在构造函数中执行此方法无效) 功能注释：每秒显示帧数
	 * 
	 * @param value
	 *            要设置的int类型值
	 */
	public void setFPS(int value) {
		_FPS = value;
		updateFrameRate(value);
	}

	/**
	 * 设置FPS为其默认值(60)。 功能注释：每秒显示帧数
	 */
	public void setFPSToDefault() {
		setFPS(60);
	}

	/**
	 * 初始值为false。 功能注释：指示是否初始化完毕
	 */
	private Boolean _IsInitialized = false;

	/**
	 * 获取IsInitialized。 功能注释：指示是否初始化完毕
	 * 
	 * @return 当前的Boolean类型的值
	 */
	public Boolean getIsInitialized() {
		return _IsInitialized;
	}

	/**
	 * 设置IsInitialized。 功能注释：指示是否初始化完毕
	 * 
	 * @param value
	 *            要设置的Boolean类型值
	 */
	public void setIsInitialized(Boolean value) {
		_IsInitialized = value;
	}

	/**
	 * 设置IsInitialized为其默认值(false)。 功能注释：指示是否初始化完毕
	 */
	public void setIsInitializedToDefault() {
		setIsInitialized(false);
	}

	/**
	 * 初始化方法，在此方法中完成游戏初始化操作，如设置帧频、加载游戏对象
	 * 
	 * @param isFirstShow
	 *            指示是否为第一次显示屏幕，如果为false则表示此次初始化是从其他程序切回时发生的
	 */
	public abstract void init(Boolean isFirstShow);

	/**
	 * 根据帧频更新帧速率值，此方法在帧频被修改时自动调用
	 * 
	 * @param FPS
	 *            帧频
	 */
	protected void updateFrameRate(int FPS) {
		frameRate = 1000 / FPS;
	}

	/**
	 * 帧速率
	 */
	int frameRate;

	/**
	 * 根据操作起始时间及当前时间计算剩余的可休息时间，以保证帧频稳定
	 * 
	 * @param beginTime
	 *            此帧中的操作起始时间
	 * @return 剩余应休眠的时间
	 */
	protected long calculateSleepTime(Date beginTime) {
		return Math.max(0, frameRate
				- (new Date().getTime() - beginTime.getTime()));
	}

	/**
	 * 更新数据函数，用于在线程中执行更新数据操作
	 */
	protected abstract void UpdateInThread();

	/**
	 * 重绘方法，用于在独立线程中执行绘图操作
	 */
	protected abstract void PaintInThread(Canvas c);

	class GameEngine extends Engine {

		private final Runnable drawrunnable = new Runnable() {
			public void run() {
				draw();
			}
		};

		protected void draw() {
			final SurfaceHolder h = getSurfaceHolder();
			Canvas c = null;
			handler.removeCallbacks(drawrunnable);
			Date beginTime = new Date();

			try {
				UpdateInThread();
				c = h.lockCanvas();
				PaintInThread(c);
				if(_IsShowFPS){
					GameWallpaperService.this.processingFPS(c, beginTime);
				}
			} finally {
				if (c != null)
					h.unlockCanvasAndPost(c);
			}

			if (_Runnable) {
				handler
						.postDelayed(drawrunnable,
								calculateSleepTime(beginTime));
			}
		}

		@Override
		public void onCreate(SurfaceHolder surfaceHolder) {
			super.onCreate(surfaceHolder);

			setTouchEventsEnabled(true);
		}

		@Override
		public void onDestroy() {
			super.onDestroy();
			handler.removeCallbacks(drawrunnable);
		}

		@Override
		public void onSurfaceCreated(SurfaceHolder holder) {
			super.onSurfaceCreated(holder);

			init(_IsFirstShow);
			_IsFirstShow = false;
			setIsInitialized(true);
			
			GameWallpaperService.this.onSurfaceCreated(holder);
		}

		@Override
		public void onSurfaceDestroyed(SurfaceHolder holder) {
			GameWallpaperService.this.onSurfaceDestroyed(holder);
			super.onSurfaceDestroyed(holder);
		}

		@Override
		public void onVisibilityChanged(boolean visible) {
			super.onVisibilityChanged(visible);
			Log.d(this.getClass().toString(), "onVisibilityChanged" + " "
					+ visible);
			setRunnable(visible);
			if (visible) {
				draw();
			} else {
				handler.removeCallbacks(drawrunnable);
			}
			GameWallpaperService.this.onVisibilityChanged(visible);
		}
		
		

		@Override
		public void onSurfaceChanged(SurfaceHolder holder, int format,
				int width, int height) {
			super.onSurfaceChanged(holder, format, width, height);
			GameWallpaperService.this.onSurfaceChanged(holder, format, width, height);
		}

		@Override
		public Bundle onCommand(String action, int x, int y, int z,
				Bundle extras, boolean resultRequested) {
			Log.d("onCommand", action);
			return GameWallpaperService.this.onCommand(action, x, y, z, extras,
					resultRequested);
		}

		@Override
		public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
			GameWallpaperService.this.onDesiredSizeChanged(desiredWidth,
					desiredHeight);
			Log.d("onDesiredSizeChanged", desiredWidth + " " + desiredHeight);
			super.onDesiredSizeChanged(desiredWidth, desiredHeight);
		}

		@Override
		public void onOffsetsChanged(float xOffset, float yOffset,
				float xOffsetStep, float yOffsetStep, int xPixelOffset,
				int yPixelOffset) {
			super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
					xPixelOffset, yPixelOffset);
			Log.d("onOffsetsChanged", xOffset + " " + yOffset);
			GameWallpaperService.this.onOffsetsChanged(xOffset, yOffset,
					xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset);
		}

		@Override
		public void onTouchEvent(MotionEvent event) {
			Log.d("onTouchEvent", event.getSize() + "");
			GameWallpaperService.this.onTouchEvent(event);
			super.onTouchEvent(event);
		};

	}

	public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
			boolean resultRequested) {
		return null;
	}

	public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {

	}

	public void onOffsetsChanged(float xOffset, float yOffset,
			float xOffsetStep, float yOffsetStep, int xPixelOffset,
			int yPixelOffset) {

	}

	public void onTouchEvent(MotionEvent event) {

	}
	
	public void onVisibilityChanged(boolean visible){
			
	}
	
	public void onSurfaceChanged(SurfaceHolder holder, int format,
			int width, int height) {
		
	}
	
	public void onSurfaceCreated(SurfaceHolder holder) {
		
	}
	
	public void onSurfaceDestroyed(SurfaceHolder holder) {
		
	}
	

	/**
	 * 用于FPS统计
	 */
	long fpsstart;
	/**
	 * 用于FPS统计
	 */
	int fpscount = 0;
	int fps;

	public void processingFPS(Canvas c, Date beginTime) {
		if (fpscount == 0)
			fpsstart = beginTime.getTime();

		fpscount++;

		if (beginTime.getTime() - fpsstart > 1000) {
			fps = fpscount - 1;
			fpscount = 0;
		}

		Paint paint = new Paint();
		paint.setColor(getFPSDrawColor());
		paint.setTextSize(getFPSDrawTextSize());
		c.drawText("FPS:" + fps, getFPSDrawPosition().getX(),
				getFPSDrawPosition().getY(), paint);
	}

	/**
	 * 初始值为false。 功能注释：指示是否显示帧频
	 */
	private boolean _IsShowFPS = false;

	/**
	 * 获取IsShowFPS。 功能注释：指示是否显示帧频
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getIsShowFPS() {
		return _IsShowFPS;
	}

	/**
	 * 设置IsShowFPS。 功能注释：指示是否显示帧频
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	private void setIsShowFPS(boolean value) {
		_IsShowFPS = value;
	}

	/**
	 * 显示FPS
	 * 
	 * @param x
	 *            X坐标
	 * @param y
	 *            Y坐标
	 * @param size
	 *            文字大小
	 * @param color
	 *            颜色
	 */
	public void showFPS(int x, int y, int size, int color) {
		setFPSDrawTextSize(size);
		setFPSDrawColor(color);
		showFPS(x, y);
	}

	/**
	 * 显示FPS
	 * 
	 * @param x
	 *            X坐标
	 * @param y
	 *            Y坐标
	 */
	public void showFPS(int x, int y) {
		getFPSDrawPosition().reset(x, y);
		showFPS();
	}

	/**
	 * 显示FPS
	 */
	public void showFPS() {
		setIsShowFPS(true);
	}

	/**
	 * 隐藏FPS
	 */
	public void hideFPS() {
		setIsShowFPS(false);
	}

	/**
	 * 初始值为new Vector2DF(10,10)。 功能注释：FPS绘制位置
	 */
	private Vector2DF _FPSDrawPosition = new Vector2DF(10, 10);

	/**
	 * 获取FPSDrawPosition。 功能注释：FPS绘制位置
	 * 
	 * @return 当前的Vector2DF类型的值
	 */
	public Vector2DF getFPSDrawPosition() {
		return _FPSDrawPosition;
	}

	/**
	 * 初始值为22。 功能注释：FPS绘制字体尺寸
	 */
	private int _FPSDrawTextSize = 22;

	/**
	 * 获取FPSDrawTextSize。 功能注释：FPS绘制字体尺寸
	 * 
	 * @return 当前的int类型的值
	 */
	public int getFPSDrawTextSize() {
		return _FPSDrawTextSize;
	}

	/**
	 * 设置FPSDrawTextSize。 功能注释：FPS绘制字体尺寸
	 * 
	 * @param value
	 *            要设置的int类型值
	 */
	public void setFPSDrawTextSize(int value) {
		_FPSDrawTextSize = value;
	}

	/**
	 * 设置FPSDrawTextSize为其默认值(22)。 功能注释：FPS绘制字体尺寸
	 */
	public void setFPSDrawTextSizeToDefault() {
		setFPSDrawTextSize(22);
	}

	/**
	 * 初始值为Color.RED。 功能注释：FPS绘制颜色
	 */
	private int _FPSDrawColor = Color.RED;

	/**
	 * 获取FPSDrawColor。 功能注释：FPS绘制颜色
	 * 
	 * @return 当前的int类型的值
	 */
	public int getFPSDrawColor() {
		return _FPSDrawColor;
	}

	/**
	 * 设置FPSDrawColor。 功能注释：FPS绘制颜色
	 * 
	 * @param value
	 *            要设置的int类型值
	 */
	public void setFPSDrawColor(int value) {
		_FPSDrawColor = value;
	}

	/**
	 * 设置FPSDrawColor为其默认值(Color.RED)。 功能注释：FPS绘制颜色
	 */
	public void setFPSDrawColorToDefault() {
		setFPSDrawColor(Color.RED);
	}
}
